#pragma once

#include <iostream>
#include <string>
#include <functional>
#include <cassert>
#include "log.hpp"
#include "sock.hpp"
#include "Epoll.hpp"

const static int gnum = 64;

class EpollServer
{
    using func_t = std::function<void(std::string)>;
public:
    EpollServer(func_t HandlerRequest, const uint16_t &port = 8080)
        : _revs_num(gnum), _port(port), _HandlerRequest(HandlerRequest)
    {
        // 申请对应返回事件的空间
        _revs = new struct epoll_event[_revs_num];
        // 创建套接字
        _listensock = Sock::Socket();
        Sock::Bind(_listensock, _port);
        Sock::Listen(_listensock);
        // 创建epoll模型
        _epfd = Epoll::CreateEpoll();
        logMessage(DEBUG, "init success, listensock: %d, epfd: %d", _listensock, _epfd);
        // 将_listensock添加到epoll中
        if (!Epoll::CtlEpoll(_epfd, EPOLL_CTL_ADD, _listensock, EPOLLIN))
            exit(6);
        logMessage(DEBUG, "add listensock to epoll success.");
    }

    void Accepter(int listensock)
    {
        std::string ip;
        uint16_t port;
        int sock = Sock::Accept(_listensock,&ip, &port);

        if(sock < 0)
        {
            logMessage(WARNING, "accept error");
            return;
        }

        //添加sock到epoll
        if(!Epoll::CtlEpoll(_epfd, EPOLL_CTL_ADD, sock, EPOLLIN)) return;//添加失败返回

        logMessage(DEBUG, "add new sock: %d to epoll success", sock);
    }
    void Recver(int sock)
    {
        char buffer[1024];
        ssize_t n = recv(sock, buffer, sizeof(buffer)-1, 0);

        //不能保证读到的是一个完整的报文
        if(n > 0)
        {
            buffer[n] = 0;
            _HandlerRequest(buffer);//处理数据
        }
        else if(n == 0)
        {
            //在epoll中去掉对sock的关心
            bool ret = Epoll::CtlEpoll(_epfd, EPOLL_CTL_DEL, sock, 0);
            assert(ret);
            //关闭sock
            close(sock);
            logMessage(NORMAL, "client %d quit, me too...", sock);
        }
        else
        {
            //在epoll中去掉对sock的关心
            bool ret = Epoll::CtlEpoll(_epfd, EPOLL_CTL_DEL, sock, 0);
            assert(ret);
            //关闭sock
            close(sock);
            logMessage(NORMAL, "client recv %d error, close error sock", sock);
        }
    }
    void HandlerEvents(int n)
    {
        assert(n > 0);

        for(int i = 0; i < n; i++)
        {
            int sock = _revs[i].data.fd;
            uint32_t events = _revs[i].events;

            if(events & EPOLLIN)//读事件就绪
            {
                if(sock ==_listensock) Accepter(_listensock);
                else Recver(sock);
            }

            if(events & EPOLLOUT)
            {
                //...
            }
        }
    }
    void LoopOnce(int timeout)
    {
        int n = Epoll::WaitEpoll(_epfd, _revs, _revs_num, timeout);

        switch (n)
        {
        case 0:
            logMessage(DEBUG, "timeout...");
            break;
        case -1:
            logMessage(WARNING, "epoll wait error: %s", strerror(errno));
            break;
        default:
            logMessage(DEBUG, "get a event");
            HandlerEvents(n);
            break;
        }
    }
    void Start()
    {
        int timeout = -1;
        while (true)
        {
            LoopOnce(timeout);
        }
    }
    ~EpollServer()
    {
        if (_listensock >= 0)
            close(_listensock);
        if (_epfd >= 0)
            close(_epfd);
        if (_revs)
            delete[] _revs;
    }

private:
    int _listensock;
    int _epfd;
    uint16_t _port;

    struct epoll_event *_revs;
    int _revs_num;

    func_t _HandlerRequest;
};